package org.geekbang.thinking.in.spring.ioc.dependency.injection.lazyinjection;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

/**
 * {@link ObjectProvider} 实现延迟依赖注入
 *
 * @author wangyh2
 * @version v1.0
 * @since 2021-09-25 14:51
 */
public class LazyAnnotationDependencyInjectionDemo {

    @Autowired
    private User user;

    @Autowired
    private ObjectProvider<User> userObjectProvider;

    @Autowired
    private ObjectFactory<List<User>> usersObjectFactory;

    @Autowired
    private ObjectProvider<User> userObjectProviders;

    public static void main(String[] args) {
        // 1、创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 2、注册 Configuration Class（配置类）
        applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);
        // 3、加载 XML 资源，解析并且生成 BeanDefinition
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
        String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
        xmlBeanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
        // 4、启动 Spring 应用上下文
        applicationContext.refresh();

        // 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
        LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);
        // 期待输出 superUser Bean
        System.out.println("demo.user = " + demo.user);
        // 期待输出 superUser Bean
        System.out.println("demo.userObjectProvider = " + demo.userObjectProvider.getObject()); // ObjectProvider 实现了 ObjectFactory

        // 期待输出 superUser user bean
        demo.usersObjectFactory.getObject().forEach(System.out::println);

        // 期待输出 superUser user bean
        demo.userObjectProviders.stream().forEach(System.out::println);

        // 6、显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
}
